#include "ET++.ph"
#ifdef __GNUG__
#pragma implementation
#endif

#include "Alert.h"

#include "Class.h"
#include "Env.h"
#include "ImageItem.h"
#include "Buttons.h"
#include "CheapText.h"
#include "StaticTView.h"
#include "StyledText.h"
#include "OrdColl.h"
#include "ObjArray.h"
#include "Window.h"
#include "Box.h"
#include "String.h"

#include "note.xpm3"
SmartBitmap gNote(note);

#include "caution.xpm3"
SmartBitmap gCaution(caution);

#include "stop.xpm3"
SmartBitmap gStop(stop);

#include "error.xpm3"
SmartBitmap gError(error);

ONEXIT(Alert)
{
	if (Alert::alerts) {
		Alert::alerts->FreeAll();
		SafeDelete(Alert::alerts);
	}
}

//---- Alert -------------------------------------------------------------------

NewMetaImpl(Alert,Dialog, (TP(text), TP(textview), TP(image), TP(buttons),
																TP(alerts)));

ObjArray *Alert::alerts;

Alert::Alert(AlertType at, const char *message, Bitmap *va_(bm), ...) : Dialog()
{
	va_list ap;
	OrdCollection *ol;
	va_start(ap,va_(bm));

	if (message) {
		text= new CheapText(message);
		textview= new StaticTextView((View*)0,
								Rectangle(gSysFont->Width('n')*45, cFit), text);

		if (va_(bm))
			image= new ImageItem(va_(bm), 0);

		if (at == eAlertMessage)
			image= textview;
		else
			image= new HBox(gPoint10, eVObjVTop, image, textview, 0);

		ol= new OrdCollection;
		char *s;
		for (int i= 0; s= va_arg(ap, char*); i++)
			ol->Add(new ActionButton(va_arg(ap, int), s, i == 0));
		buttons= new HBox(20, (VObjAlign)(eVObjVBase|eVObjHEqual|eVObjHExpand), ol);
	}
	va_end(ap);
}

Alert::~Alert()
{
	SafeDelete(text);
}

int Alert::ShowF(const char *va_(fmt), ...)
{
	int code;
	va_list ap;

	va_start(ap,va_(fmt));
	code= ShowV(va_(fmt), ap);
	va_end(ap);
	return code;
}

int Alert::ShowV(const char *fmt, va_list ap)
{
	return ShowV(gSysFont, fmt, ap);
}

int Alert::ShowV(Font *fp, const char *fmt, va_list ap)
{
	char *buf= strvprintf(fmt, ap);
	SafeDelete(text);
	text= new StyledText(fp, buf);
	SafeDelete(buf);
	textview->SetText(text);
	textview->SetExtent(Point(textview->GetExtent().x, cFit));
	return Dialog::ShowUnderMouse();
}

VObject *Alert::DoMakeControls()
{
	return image;
}

VObject *Alert::DoMakeActions()
{
	return buttons;
}

void Alert::InspectorId(char *buf, int sz)
{
	if (textview)
		textview->InspectorId(buf, sz);
	else
		Dialog::InspectorId(buf, sz);
}

//---- global entry points -----------------------------------------------------

static Alert *GetAlert(AlertType at)
{
	Alert *al= 0;

	if (Alert::alerts == 0)
		Alert::alerts= new ObjArray((int)eAlertError);
		
	if ((al= (Alert*) Alert::alerts->At(at)) == 0) {
		switch (at) {
		case eAlertNote:
			al= new Alert(at, "note", gNote, "OK", cIdOk, 0);
			break;
		case eAlertCaution:
			al= new Alert(at, "Caution", gCaution,
						"Yes",    cIdYes,
						"No",     cIdNo,
						"Cancel", cIdCancel, 0);
			break;
		case eAlertStop:
			al= new Alert(at, "Stop", gStop,
						"Yes",    cIdYes,
						"No",     cIdNo,
						"Cancel", cIdCancel, 0);
			break;
		case eAlertError:
			if (Env::GetValue("Application.DebugButtonInAlert", FALSE))
				al= new Alert(at, "Error", gError,
						"Ignore",     cIdIgnore,
						"Dump Core",  cIdAbort,
						"Debug",      cIdInspect, 0);
			else
				al= new Alert(at, "Error", gError,
						"Ignore",     cIdIgnore,
						"Dump Core",  cIdAbort, 0);
			break;
		case eAlertSun:
		case eAlertMessage:
			al= new Alert(at, "Message", 0, "Ok", cIdOk, 0);
			break;
		}
		if (al)
			Alert::alerts->AtPut(at, al);
	}

	return al;
}

int ShowAlert(AlertType at, const char* va_(fmt), ...)
{
	int code= 0;
	va_list ap;
	Alert *al;

	va_start(ap, va_(fmt));
	al= GetAlert(at);
	if (al)
		code= al->ShowV(va_(fmt), ap);
	va_end(ap);
	return code;
}

int ShowAlert(AlertType at, Font *fp, const char* va_(fmt), ...)
{
	int code= 0;
	va_list ap;
	Alert *al;

	va_start(ap, va_(fmt));
	al= GetAlert(at);
	if (al)
		code= al->ShowV(fp, va_(fmt), ap);
	va_end(ap);
	return code;
}

